{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "07W9tE81x6Ky",
    "outputId": "db9e9a68-2624-49e3-f419-688bd18e4a85"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<torch._C.Generator at 0x7fd5d0164110>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from datasets import load_dataset\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "\n",
    "torch.manual_seed(12046)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "id": "ChYX0H9jx6K2"
   },
   "outputs": [],
   "source": [
    "# 一些超参数\n",
    "learning_rate = 1e-3\n",
    "# 如果有GPU，该脚本将使用GPU进行计算\n",
    "device = 'cuda' if torch.cuda.is_available() else 'cpu'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "lrW4ceQUx6K3"
   },
   "outputs": [],
   "source": [
    "raw_datasets = load_dataset('code_search_net', 'python')\n",
    "datasets = raw_datasets['train'].filter(lambda x: 'apache/spark' in x['repository_name'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "B1diphqUx6K3"
   },
   "outputs": [],
   "source": [
    "class char_tokenizer:\n",
    "\n",
    "    def __init__(self, data):\n",
    "        # 数据中出现的所有字符构成字典\n",
    "        chars = sorted(list(set(''.join(data))))\n",
    "        # 预留一个位置给结尾的特殊字符\n",
    "        self.char2ind = {s : i + 1 for i, s in enumerate(chars)}\n",
    "        self.char2ind['<|e|>'] = 0\n",
    "        self.ind2char = {i : s for s, i in self.char2ind.items()}\n",
    "\n",
    "    def encode(self, text):\n",
    "        return [self.char2ind[c] for c in text]\n",
    "\n",
    "    def decode(self, enc):\n",
    "        if isinstance(enc, int):\n",
    "            return self.ind2char[enc]\n",
    "        return [self.ind2char[i] for i in enc]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "YhaYe9rtx6K4",
    "outputId": "b6bea146-53d5-483c-b32e-a07d553e233e"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('def post(self):', 98)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 举例验证分词器\n",
    "tok = char_tokenizer(datasets['whole_func_string'])\n",
    "example_text = 'def post(self):'\n",
    "''.join(tok.decode(tok.encode(example_text))), len(tok.char2ind)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "9zIh_XMzx6K4"
   },
   "outputs": [],
   "source": [
    "class RNNCell(nn.Module):\n",
    "\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        '''\n",
    "        循环神经网络的神经元\n",
    "        参数\n",
    "        ----\n",
    "        input_size ：int，输入数据的特征长度\n",
    "        hidden_size ：int，隐藏状态的特征长度\n",
    "        '''\n",
    "        super().__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        combined_size = self.input_size + self.hidden_size\n",
    "        # 使用线性回归模型，由输入数据和上一个隐藏状态得到当前的隐藏状态\n",
    "        self.i2h = nn.Linear(combined_size, self.hidden_size)\n",
    "\n",
    "    def forward(self, inputs, hidden=None):\n",
    "        '''\n",
    "        向前传播\n",
    "        参数\n",
    "        ----\n",
    "        inputs ：torch.FloatTensor，输入数据，形状为(1, I)，I等于input_size\n",
    "        hidden ：torch.FloatTensor，上一个隐藏状态，形状为(1, H)，H等于hidden_size\n",
    "        返回\n",
    "        ----\n",
    "        hidden ：torch.FloatTensor，当前隐藏状态\n",
    "        '''\n",
    "        # 若无上一个隐藏状态，比如循环神经网络的开端，则生成默认的隐藏状态\n",
    "        if hidden is None:\n",
    "            hidden = self.init_hidden(inputs.device)   # (1,     H)\n",
    "        combined = torch.cat((inputs, hidden), dim=1)  # (1, I + H)\n",
    "        hidden = F.relu(self.i2h(combined))            # (1,     H)\n",
    "        return hidden\n",
    "\n",
    "    def init_hidden(self, device):\n",
    "        # 默认的隐藏状态全部等于0\n",
    "        # device用于控制生成张量的设备（cpu或gpu）\n",
    "        return torch.zeros((1, self.hidden_size), device=device)\n",
    "\n",
    "\n",
    "class CharRNN(nn.Module):\n",
    "\n",
    "    def __init__(self, vs):\n",
    "        '''\n",
    "        单层的循环神经网络\n",
    "        参数\n",
    "        ----\n",
    "        vs ：int，字典大小\n",
    "        '''\n",
    "        super().__init__()\n",
    "        # 定义文字嵌入的特征长度\n",
    "        self.emb_size = 30\n",
    "        # 定义隐藏状态的特征长度\n",
    "        self.hidden_size = 50\n",
    "        # 文字嵌入层\n",
    "        self.embedding = nn.Embedding(vs, self.emb_size)\n",
    "        # 循环神经网络的神经元\n",
    "        self.rnn = RNNCell(self.emb_size, self.hidden_size)\n",
    "        # 语言建模头，根据隐藏状态预测下一个字母是什么\n",
    "        self.h2o = nn.Linear(self.hidden_size, vs)\n",
    "\n",
    "    def forward(self, x, hidden=None):\n",
    "        '''\n",
    "        向前传播\n",
    "        参数\n",
    "        ----\n",
    "        x ：torch.LongTensor，当前字母在字典中的位置，形状为(1)\n",
    "        hidden ：torch.FloatTensor，上一个隐藏状态，形状为(1, 50)\n",
    "        返回\n",
    "        ----\n",
    "        output ：torch.FloatTensor，预测结果的logits，形状为(1, vs)\n",
    "        hidden ：torch.FloatTensor，当前隐藏状态\n",
    "        '''\n",
    "        emb = self.embedding(x)         # (1, 30)\n",
    "        # 得到当前的隐藏状态\n",
    "        hidden = self.rnn(emb, hidden)  # (1, 50)\n",
    "        # 预测下一个字母\n",
    "        output = self.h2o(hidden)       # (1, vs)\n",
    "        return output, hidden\n",
    "\n",
    "c_model = CharRNN(len(tok.char2ind)).to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "frHZYPQSx6K6",
    "outputId": "a40e747e-8053-4f36-c5e8-02ec382d8fb4"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(torch.Size([1, 98]), torch.Size([1, 50]))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过一个简单的例子验证模型搭建是否正确\n",
    "inputs = torch.tensor(tok.encode('d'), device=device)\n",
    "hidden = None\n",
    "logits, hidden = c_model(inputs, hidden)\n",
    "logits.shape, hidden.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "id": "3uo7Pzlqx6K6"
   },
   "outputs": [],
   "source": [
    "@torch.no_grad()\n",
    "def generate(model, idx, max_new_tokens=300):\n",
    "    '''\n",
    "    利用模型生成文本（反复使用模型进行预测）\n",
    "    参数\n",
    "    ----\n",
    "    model ：CharRNN，生成文本的模型\n",
    "    idx ：torch.LongTensor，当前字母在字典中的位置，形状为(1)\n",
    "    max_new_tokens ：int，生成文本的最大长度\n",
    "    返回\n",
    "    ----\n",
    "    out ：list[int]，生成的文本\n",
    "    '''\n",
    "    out = idx.tolist()\n",
    "    hidden = None\n",
    "    # 将模型切换至评估模式\n",
    "    model.eval()\n",
    "    for _ in range(max_new_tokens):\n",
    "        logits, hidden = model(idx, hidden)\n",
    "        probs = F.softmax(logits, dim=-1)\n",
    "        # 根据模型预测的概率，得到最终的预测结果（下一个字母）\n",
    "        # 这一步运算有一定随机性\n",
    "        ix = torch.multinomial(probs, num_samples=1)\n",
    "        out.append(ix.item())\n",
    "        # 注意调整模型输入的形状\n",
    "        idx = ix.squeeze(0)\n",
    "        if ix.item() == 0:\n",
    "            break\n",
    "    # 将模型切换至训练模式\n",
    "    model.train()\n",
    "    return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "QQ2MFkLWx6K6",
    "outputId": "ad58eda7-3141-427d-cbc9-ecf782f9ce04"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "d*ZO(F/of(\"YP{BZE G|uw=R:1'_$?Q9)N[{KQ=CKfAM:iKca\"|+Q3j<sAegWS$ö8Px!q9T3\"yum5Za)'W~5\\Wm&B\"({r\n",
      "cdtMR^DA11zc<|e|>\n"
     ]
    }
   ],
   "source": [
    "# 使用模型来生成文本\n",
    "begin_text = torch.tensor(tok.encode('d'), device=device)\n",
    "print(''.join(tok.decode(generate(c_model, begin_text))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "F-OErxYDx6K6",
    "outputId": "ed49a77a-26c1-4e40-ac70-3a22c3a9a9cb"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85, 71, 78, 72, 11, 28],\n",
      "       device='cuda:0')\n",
      "tensor([71, 72,  2, 82, 81, 85, 86, 10, 85, 71, 78, 72, 11, 28,  0],\n",
      "       device='cuda:0')\n",
      "The input is tensor([70], device='cuda:0'), the implied input is tensor([70], device='cuda:0'), the target is 71\n",
      "The input is tensor([71], device='cuda:0'), the implied input is tensor([70, 71], device='cuda:0'), the target is 72\n",
      "The input is tensor([72], device='cuda:0'), the implied input is tensor([70, 71, 72], device='cuda:0'), the target is 2\n",
      "The input is tensor([2], device='cuda:0'), the implied input is tensor([70, 71, 72,  2], device='cuda:0'), the target is 82\n",
      "The input is tensor([82], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82], device='cuda:0'), the target is 81\n",
      "The input is tensor([81], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81], device='cuda:0'), the target is 85\n",
      "The input is tensor([85], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85], device='cuda:0'), the target is 86\n",
      "The input is tensor([86], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86], device='cuda:0'), the target is 10\n",
      "The input is tensor([10], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10], device='cuda:0'), the target is 85\n",
      "The input is tensor([85], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85], device='cuda:0'), the target is 71\n",
      "The input is tensor([71], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85, 71], device='cuda:0'), the target is 78\n",
      "The input is tensor([78], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85, 71, 78], device='cuda:0'), the target is 72\n",
      "The input is tensor([72], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85, 71, 78, 72], device='cuda:0'), the target is 11\n",
      "The input is tensor([11], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85, 71, 78, 72, 11],\n",
      "       device='cuda:0'), the target is 28\n",
      "The input is tensor([28], device='cuda:0'), the implied input is tensor([70, 71, 72,  2, 82, 81, 85, 86, 10, 85, 71, 78, 72, 11, 28],\n",
      "       device='cuda:0'), the target is 0\n"
     ]
    }
   ],
   "source": [
    "def encoding(text):\n",
    "    '''\n",
    "    根据文本生成训练数据\n",
    "    '''\n",
    "    enc = tok.encode(text)\n",
    "    # 0表示文本的结束\n",
    "    return (torch.tensor(enc, device=device), torch.tensor(enc[1:] + [0], device=device))\n",
    "\n",
    "# 用一个简单的例子展示模型的训练数据\n",
    "inputs, labels = encoding(example_text)\n",
    "print(inputs)\n",
    "print(labels)\n",
    "for i in range(len(inputs)):\n",
    "    context = inputs[:i + 1]\n",
    "    target = labels[i]\n",
    "    print(f'The input is {inputs[i].unsqueeze(0)}, ' +\n",
    "          f'the implied input is {context}, the target is {target}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "id": "JDtx4jTix6K7"
   },
   "outputs": [],
   "source": [
    "# 记录模型的损失\n",
    "lossi = []\n",
    "epochs = 1\n",
    "optimizer = optim.Adam(c_model.parameters(), lr=learning_rate)\n",
    "\n",
    "for epoch in range(epochs):\n",
    "    for data in datasets:\n",
    "        inputs, labels = encoding(data['whole_func_string'])\n",
    "        # 初始化\n",
    "        hidden = None\n",
    "        loss = torch.tensor([0.], device=device)\n",
    "        optimizer.zero_grad()\n",
    "        lens = inputs.shape[0]\n",
    "        # 遍历文本，累加模型损失\n",
    "        for i in range(lens):\n",
    "            # 使用unsqueeze调整训练数据的形状\n",
    "            logits, hidden = c_model(inputs[i].unsqueeze(0), hidden)\n",
    "            loss += F.cross_entropy(logits, labels[i].unsqueeze(0)) / lens\n",
    "        lossi.append(loss.item())\n",
    "        loss.backward()\n",
    "        optimizer.step()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 448
    },
    "id": "XHceUlaBx6K7",
    "outputId": "36e4c82d-4214-4d74-eac7-28489e595a7e"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fd46c0b9810>]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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1K0r94VZX6mf5Qvr169HaWkpgsEgbr31Vrz44osYMWJEp+qD+fPnY82aNZgzZ47hs87SD5MnT8ZTTz2FN954A3PnzsXOnTtx3nnnob6+vtP0AQDs2LEDc+fOxeDBg/Hmm2/itttuw3//93/jb3/7G4DOeZ986aWXUFNTgxtvvBFAx/8m8mK2X0LSwaxZs7Bhwwa8//772W5KVhg6dCjWrVuH2tpaPP/887jhhhuwePHibDerw9i7dy/uuOMOLFiwAIWFhdluTtb43Oc+p70eM2YMJk+ejAEDBuBf//oXioqKstiyjiUajWLSpEm45557AADjx4/Hhg0b8Oc//xk33HBDlluXHf7617/ic5/7HHr37p2V43dKC0n37t3h8/kMkcKHDx9GdXV1llrVcajnaHf+1dXVOHLkiO7zcDiMEydO5GUf3X777XjllVfw7rvvom/fvtry6upqtLW1oaamRre+3BdmfaV+li8EAgEMGjQIEydOxJw5czB27Fg8+OCDnaYPVq9ejSNHjmDChAnw+/3w+/1YvHgxHnroIfj9flRVVXWKfpCprKzEkCFDsH379k5zLQBAr169MGLECN2y4cOHa+6rznaf3L17N95++23cfPPN2rKOvh46pSAJBAKYOHEiFi5cqC2LRqNYuHAhpkyZksWWdQwDBw5EdXW17vzr6uqwYsUK7fynTJmCmpoarF69WlvnnXfeQTQaxeTJkzu8zcmiKApuv/12vPjii3jnnXcwcOBA3ecTJ05EQUGBri+2bNmCPXv26Ppi/fr1uhvPggULUF5ebrih5RPRaBStra2dpg8uuugirF+/HuvWrdP+Jk2ahOuvv1573Rn6QaahoQGffvopevXq1WmuBQA455xzDCUAtm7digEDBgDoXPdJAHjyySfRs2dPTJ8+XVvW4ddDWsJy85D58+crwWBQeeqpp5RNmzYp3/rWt5TKykpdpHA+U19fr6xdu1ZZu3atAkD5/e9/r6xdu1bZvXu3oiixdLbKykrl5ZdfVj7++GPlyiuvNE1nGz9+vLJixQrl/fffVwYPHpxX6WyKoii33XabUlFRoSxatEiX2tbU1KStc+uttyr9+/dX3nnnHWXVqlXKlClTlClTpmifq2ltl1xyibJu3TrljTfeUHr06JFXaY4/+tGPlMWLFys7d+5UPv74Y+VHP/qR4vF4lLfeektRlM7RB2aIWTaK0jn64Xvf+56yaNEiZefOncoHH3ygTJs2Tenevbty5MgRRVE6Rx8oSiz12+/3K3fffbeybds25emnn1aKi4uVefPmaet0lvtkJBJR+vfvr/zwhz80fNaR10OnFSSKoih//OMflf79+yuBQEA566yzlOXLl2e7SWnj3XffVQAY/m644QZFUWIpbT/72c+UqqoqJRgMKhdddJGyZcsW3T6OHz+uXHfddUppaalSXl6ufOMb31Dq6+uzcDbJY9YHAJQnn3xSW6e5uVn5zne+o3Tp0kUpLi5WrrrqKuXgwYO6/ezatUv53Oc+pxQVFSndu3dXvve97ymhUKiDzyZ5vvnNbyoDBgxQAoGA0qNHD+Wiiy7SxIiidI4+MEMWJJ2hH6699lqlV69eSiAQUPr06aNce+21utobnaEPVP7v//5PGTVqlBIMBpVhw4Ypjz32mO7zznKffPPNNxUAhnNTlI69HjyKoiiubTuEEEIIIWmkU8aQEEIIISS3oCAhhBBCSNahICGEEEJI1qEgIYQQQkjWoSAhhBBCSNahICGEEEJI1qEgIYQQQkjWoSAhhBBCSNahICGEEEJI1qEgIYQQQkjWoSAhhBBCSNahICGEEEJI1vn/PHanfwPUIMMAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(lossi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "cPmymAa3x6K7",
    "outputId": "9e5348b0-c1a6-4b75-9f93-95b556b69711"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "def.areartT    civeif the _are _sext(am pestranatucbyessedevcet \"cot che = srd Not Fit the = Notintorn aresTiveb), essingparte = pe \"ome   retiothe ted th ches %\"ist(mogthar:c_Sy\"\n",
      "      or on Jngien pyrame dor it = veri/g():\n",
      "    siltonf_ante   \"\"\"\n",
      "            sedenv)<|e|>\n"
     ]
    }
   ],
   "source": [
    "# 使用模型来生成文本\n",
    "begin_text = torch.tensor(tok.encode('d'), device=device)\n",
    "print(''.join(tok.decode(generate(c_model, begin_text))))"
   ]
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "gpuType": "V100",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
